home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Harvest C 1.3 / Source Code / gen68k.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  52.8 KB  |  1,773 lines  |  [TEXT/ALFA]

  1. /*
  2.     Harvest C
  3.     Copyright 1992 Eric W. Sink.  All rights reserved.
  4.     
  5.     This file is part of Harvest C.
  6.     
  7.     Harvest C is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU Generic Public License as published by
  9.     the Free Software Foundation; either version 2, or (at your option)
  10.     any later version.
  11.     
  12.     Harvest C is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.     
  17.     You should have received a copy of the GNU General Public License
  18.     along with Harvest C; see the file COPYING.  If not, write to
  19.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.     
  21.     Harvest C is not in any way a product of the Free Software Foundation.
  22.     Harvest C is not GNU software.
  23.     Harvest C is not public domain.
  24.  
  25.     This file may have other copyrights which are applicable as well.
  26.  
  27. */
  28.  
  29. /*
  30.  * Harvest C
  31.  * 
  32.  * Copyright 1991 Eric W. Sink   All rights reserved.
  33.  * 
  34.  * This file contains routines for 68k code generation.  The result is a set of
  35.  * data structures representing 68k instructions and data. The routines here
  36.  * do not output assembly source.
  37.  * 
  38.  * 
  39.  */
  40.  
  41.  
  42. #include "conditcomp.h"
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include "structs.h"
  46.  
  47. #include "CHarvestDoc.h"
  48. #include "CHarvestOptions.h"
  49.  
  50. extern CHarvestDoc *gProject;
  51.  
  52. #pragma segment CodeGenMisc
  53.  
  54. extern LabSYMVia_t NextFuncSegment;
  55.  
  56. /*
  57.  * This file and its friends contain routines used for generating 68000
  58.  * assembly code from the symbol table / parse tree.  These routines convert
  59.  * data structures to data structures.  The result is a data structure
  60.  * representing 68000 instructions.  It is the job of another module to
  61.  * handle the outputting of these data structures as assembler source or
  62.  * linker files or whatever is desired.
  63.  */
  64.  
  65. /*
  66.  * The routines used for generating 68000 instructions for the various
  67.  * statements and expressions will resemble the parser.  The important data
  68.  * structure with respect to the expressions is the LocAM.  This data
  69.  * structure simply stores an addressing mode which specifies where the
  70.  * operand is "currently" located.  A general routine to generate code for an
  71.  * expression will accept the parse tree as an argument and generate 68000
  72.  * instruction records into the current list of instructions, and return the
  73.  * LocAM data structure, specifying where the result is located. There will
  74.  * be roughly one routine for each type of expression or statement, just as
  75.  * in the parser, and each routine will potentially call several others,
  76.  * recursively calling itself, as in the parser.  _Statements_ need not
  77.  * return an addressing mode, as they have no result value.  A 68000
  78.  * instruction record must store the opcode, both operands, size, the label
  79.  * for that instruction. An operand stores an addressing mode and its size.
  80.  * In the process of generating expressions, temporary registers will be
  81.  * needed.
  82.  */
  83.  
  84. /*
  85.  * During the code generation of expressions, we often want to ensure that
  86.  * some value is in a register, so that we may do operations on it which are
  87.  * restricted to register modes.  Also, we want values to be placed in
  88.  * temporary places so that intermediate value will not clobber variables.
  89.  * For example, x = a + b, where all three are locals on the stack frame.  We
  90.  * do not want to simply add a to b and move the result to x, because this
  91.  * has the side effect of changing b.  So, we ensure that b is moved to a
  92.  * register before doing the addition.  The problem is that there are a
  93.  * limited number of temporary registers. What happens when we request a
  94.  * temporary register, and they are all full ? Well, we spill the value in
  95.  * some register onto the stack, and give the register to the value which
  96.  * requested it.  So, the problem now is : What happens when we want the
  97.  * value that WAS in the register ?  Well, it must be retrieved from the
  98.  * stack.  When we retrieve something from the stack, what happens if the
  99.  * register we are retrieving it into is currently full ?  When we retrieve
  100.  * something from the stack, what happens if its not on top of the stack ?
  101.  * Are there situations where this can come up ?
  102.  */
  103.  
  104. InstVia_t
  105. RawInstruction(void)
  106. {
  107.     InstVia_t                       raw;
  108.     raw = Ealloc(sizeof(Inst_t));
  109.     if (raw) {
  110.     Via(raw)->OP = 0;
  111.     Via(raw)->left = NULL;
  112.     Via(raw)->right = NULL;
  113.     Via(raw)->SZ = M68sz_none;
  114.     Via(raw)->prev = NULL;
  115.     Via(raw)->Address = -1;
  116.     Via(raw)->InstSize = -1;
  117.     Via(raw)->Bytes[0] = 0;
  118.     Via(raw)->next = NULL;
  119.     }
  120.     return raw;
  121. }
  122.  
  123. InstListVia_t
  124. RawInstructionList(void)
  125. {
  126.     InstListVia_t                   raw;
  127.     raw = Ealloc(sizeof(InstList_t));
  128.     if (raw) {
  129.     Via(raw)->head = NULL;
  130.     Via(raw)->tail = NULL;
  131.     Via(raw)->count = 0;
  132.     Via(raw)->PendingLabel = NULL;
  133.     }
  134.     return raw;
  135. }
  136.  
  137. enum Size68
  138. M68_TypeSize(TypeRecordVia_t TP)
  139. /*
  140.  * Returns the size of a type, for the purpose of the size field of an
  141.  * instruction.  The routine is really only necessary because of the 68881
  142.  * code generator.
  143.  */
  144. {
  145.     if (isFloatingType(TP)) {
  146.     if (gProject->itsOptions->useMC68881) {
  147.         if (GetTPKind(TP) == TRC_float) {
  148.         return M68sz_single;
  149.         } else if (GetTPKind(TP) == TRC_double) {
  150.         return M68sz_double;
  151.         } else {
  152.         return M68sz_extended;
  153.         }
  154.     } else {
  155.         return GetTPSize(TP);
  156.     }
  157.     } else if (isPointerType(TP)) {
  158.     return M68sz_long;
  159.     } else if (isArrayType(TP)) {
  160.     return M68sz_long;
  161.     } else if (isFunctionType(TP)) {
  162.     /* Should probably generate a warning here. */
  163.     return M68sz_long;
  164.     } else {
  165.     return GetTPSize(TP);
  166.     }
  167. }
  168.  
  169. void
  170. GenLoadEA(LocAMVia_t loc, LocAMVia_t dst, InstListVia_t Codes)
  171. /*
  172.  * This routine is called when we want to LEA something, generally when we
  173.  * want the address of something.
  174.  */
  175. {
  176.     assert(GetLocAM(loc) != M68am_DReg);
  177.     if (GetLocAM(loc) == M68am_ARegIndirect) {
  178.     GenInst(M68op_MOVE, M68sz_long, BuildARegDirect(GetLocAReg(loc)),
  179.         dst, Codes);
  180.     } else {
  181.     GenInst(M68op_LEA, M68sz_none, loc, dst, Codes);
  182.     }
  183. }
  184.  
  185. void
  186. GenPushEA(LocAMVia_t loc, InstListVia_t Codes)
  187. /*
  188.  * This routine is called when we want to PEA something, generally when we
  189.  * want the address of something.
  190.  */
  191. {
  192.     if (GetLocAM(loc) == M68am_ARegIndirect) {
  193.         GenInst(M68op_MOVE, M68sz_long, BuildARegDirect(GetLocAReg(loc)),
  194.             BuildARegPreDec(7), Codes);
  195.     } else {
  196.         GenInst(M68op_PEA, M68sz_none, loc, NULL, Codes);
  197.     }
  198. }
  199.  
  200. LocAMVia_t
  201. GenSANECall(unsigned short Cmd, LocAMVia_t src, LocAMVia_t dst, InstListVia_t Codes)
  202. /* This routine generates a call to SANE. */
  203. {
  204.     /*
  205.      * We  make sure both operands are in spill slots, and pea of both, src
  206.      * first.  Then we push the Cmd word, and generate _FP68K
  207.      */
  208.  
  209.     if (src)
  210.     GenPushEA(src, Codes);
  211.     if (dst)
  212.     GenPushEA(dst, Codes);
  213.     GenPush(BuildImmediate(Cmd, M68sz_word), Codes);
  214.     GenInst(M68op_FP68K, M68sz_none, NULL, NULL, Codes);
  215.     return dst;
  216. }
  217.  
  218. void
  219. Genmoverange(int size, LocAMVia_t src, LocAMVia_t dst, InstListVia_t Codes)
  220. {
  221.     /*
  222.      * This routine handles a move of any even number of bytes from one
  223.      * location to another.  It is used for struct assignment, moving of
  224.      * doubles, etc...
  225.      */
  226.     LocAMVia_t                      fromA = NULL;
  227.     LocAMVia_t                      toA = NULL;
  228.     LocAMVia_t                      fromTemp = NULL;
  229.     LocAMVia_t                      toTemp = NULL;
  230.     int                             dstoff = 0;
  231.     int                             srcoff = 0;
  232.     int                             dsttmp = 0;
  233.     int                             srctmp = 0;
  234.     int                             ndx = 0;
  235.     if (GetLocAM(dst) == M68am_ARegPreDec) {
  236.     /* This is usually a stack push. */
  237.     fromA = TempAddrReg(Codes);
  238.     SetLocAM(fromA, M68am_ARegDirect);
  239.     if (GetLocAM(src) == M68am_DReg) {
  240.         Gen68Error("Can't LEA a D reg");
  241.     }
  242.     GenLoadEA(src, fromA, Codes);
  243.     ndx = size;
  244.     while (ndx) {
  245.         if (ndx == 2) {
  246.         fromTemp = BuildARegDisplace(GetLocAReg(fromA), ndx - 2);
  247.         GenInst(M68op_MOVE, M68sz_word, fromTemp, dst, Codes);
  248.         ndx -= 2;
  249.         } else {
  250.         fromTemp = BuildARegDisplace(GetLocAReg(fromA), ndx - 4);
  251.         GenInst(M68op_MOVE, M68sz_long, fromTemp, dst, Codes);
  252.         ndx -= 4;
  253.         }
  254.     }
  255.     FreeTemp(fromA);
  256.     } else {
  257.     srctmp = dsttmp = 0;
  258.     if (GetLocAM(src) == M68am_ARegDisplace) {
  259.         fromA = BuildARegDisplace(GetLocAReg(src), GetLocConstant(src));
  260.         srcoff = GetLocConstant(src);
  261.     } else if (GetLocAM(src) == M68am_ARegIndirect) {
  262.         fromA = BuildARegDisplace(GetLocAReg(src), 0);
  263.         srcoff = 0;
  264.     } else {
  265.         srctmp = 1;
  266.         fromA = TempAddrReg(Codes);
  267.         SetLocAM(fromA, M68am_ARegDirect);
  268.         GenLoadEA(src, fromA, Codes);
  269.         srcoff = 0;
  270.     }
  271.     if (GetLocAM(dst) == M68am_ARegPostInc) {
  272.         toTemp = dst;
  273.     } else if (GetLocAM(dst) == M68am_ARegDisplace) {
  274.         toTemp = BuildARegDisplace(GetLocAReg(dst), GetLocConstant(dst));
  275.         dstoff = GetLocConstant(dst);
  276.     } else if (GetLocAM(dst) == M68am_ARegIndirect) {
  277.         toTemp = BuildARegDisplace(GetLocAReg(dst), 0);
  278.         dstoff = 0;
  279.     } else {
  280.         dsttmp = 1;
  281.         toA = TempAddrReg(Codes);
  282.         SetLocAM(toA, M68am_ARegDirect);
  283.         GenLoadEA(dst, toA, Codes);
  284.         toTemp = BuildARegPostInc(GetLocAReg(toA));
  285.         dstoff = 0;
  286.     }
  287.     ndx = 0;
  288.     while (ndx < size) {
  289.         fromTemp = BuildARegDisplace(GetLocAReg(fromA), srcoff);
  290.         if (GetLocAM(toTemp) == M68am_ARegDisplace) {
  291.         toTemp = BuildARegDisplace(GetLocAReg(toTemp), dstoff);
  292.         }
  293.         if ((size - ndx) == 2) {
  294.         GenInst(M68op_MOVE, M68sz_word, fromTemp, toTemp, Codes);
  295.         ndx += 2;
  296.         srcoff += 2;
  297.         dstoff += 2;
  298.         } else {
  299.         GenInst(M68op_MOVE, M68sz_long, fromTemp, toTemp, Codes);
  300.         ndx += 4;
  301.         srcoff += 4;
  302.         dstoff += 4;
  303.         }
  304.     }
  305.     if (srctmp) {
  306.         FreeTemp(fromA);
  307.     }
  308.     if (dsttmp) {
  309.         FreeTemp(toA);
  310.     }
  311.     }
  312. }
  313.  
  314. int
  315. is68881SZ(enum Size68 size)
  316. {
  317.     switch (size) {
  318.     case M68sz_single:
  319.     case M68sz_double:
  320.     case M68sz_extended:
  321.     return 1;
  322.     break;
  323.     default:
  324.     return 0;
  325.     break;
  326.     }
  327. }
  328.  
  329. void
  330. Genmove(enum Size68 size, LocAMVia_t src, LocAMVia_t dst, InstListVia_t Codes)
  331. {
  332.     /*
  333.      * This is a general purpose move routine, to move any operand to any
  334.      * other operand.
  335.      */
  336.  
  337.     if (size == M68sz_none) {
  338.     Gen68Error("Missing size in gen68_move");
  339.     }
  340.     if ((GetLocAM(src) == M68am_FReg) || (GetLocAM(dst) == M68am_FReg)) {
  341.     GenInst(M68op_FMOVE, size, src, dst, Codes);
  342.     } else {
  343.     if (is68881SZ(size)) {
  344.         if (SizeOfFloat == SizeOfDouble) {
  345.         Genmoverange(SizeOfDouble, src, dst, Codes);
  346.         } else {
  347.         if (size == M68sz_single) {
  348.             GenInst(M68op_MOVE, M68sz_long, src, dst, Codes);
  349.         } else if (size == M68sz_double) {
  350.             Genmoverange(SizeOfDouble, src, dst, Codes);
  351.         } else {
  352.             Genmoverange(SizeOfLongDouble, src, dst, Codes);
  353.         }
  354.         }
  355.     } else if ((LocIsFloat(src)) || (LocIsFloat(dst))) {
  356.         if (GetLocSZ(src) == GetLocSZ(dst)) {
  357.         Genmoverange(GetLocSZ(dst), src, dst, Codes);
  358.         } else {        /* different sizes (conversion) */
  359.         LocAMVia_t                      ftemp;
  360.         if (GetLocSZ(src) == SizeOfFloat) {
  361.             if (GetLocSZ(dst) == SizeOfDouble) {
  362.             ftemp = TempFloatReg(Codes);
  363.             GenSANECall(FFSGL + FOZ2X, src, ftemp, Codes);
  364.             GenSANECall(FFDBL + FOX2Z, ftemp, dst, Codes);
  365.             } else {    /* extended */
  366.             GenSANECall(FFSGL + FOZ2X, src, dst, Codes);
  367.             }
  368.         } else if (GetLocSZ(src) == SizeOfDouble) {
  369.             if (GetLocSZ(dst) == SizeOfFloat) {
  370.             ftemp = TempFloatReg(Codes);
  371.             GenSANECall(FFDBL + FOZ2X, src, ftemp, Codes);
  372.             GenSANECall(FFSGL + FOX2Z, ftemp, dst, Codes);
  373.             } else {    /* extended */
  374.             GenSANECall(FFDBL + FOZ2X, src, dst, Codes);
  375.             }
  376.         } else {    /* extended */
  377.             if (GetLocSZ(dst) == SizeOfFloat) {
  378.             GenSANECall(FFSGL + FOX2Z, src, dst, Codes);
  379.             } else {    /* double */
  380.             GenSANECall(FFDBL + FOX2Z, src, dst, Codes);
  381.             }
  382.         }
  383.         }
  384.     } else if (size > 4) {
  385.         Genmoverange(size, src, dst, Codes);
  386.     } else {
  387.         GenInst(M68op_MOVE, size, src, dst, Codes);
  388.     }
  389.     }
  390. }
  391.  
  392. SpillSlotVia_t
  393. GetLocalSlot(TypeRecordVia_t TP)
  394. /*
  395.  * Gets a spill slot specifically designed to be used for a local variable.
  396.  */
  397. {
  398.     SpillSlotVia_t                  result;
  399.     if (isArrayType(TP)) {
  400.     result = GetSpillSlot(GetTPSize(TP));
  401.     } else {
  402.     result = GetSpillSlot(M68_TypeSize(TP));
  403.     }
  404.     Via(result)->local = 1;
  405.     return result;
  406. }
  407.  
  408. void
  409. AddInstruction(InstVia_t inst, InstListVia_t Codes)
  410. /*
  411.  * Adds an instruction to the instruction list passed.  If the instruction is
  412.  * a label, then that label is set as the pending label for that list.  If
  413.  * there is a pending label for the list, that label is assigned to point to
  414.  * the given instruction, even if that instruction is yet another label.
  415.  */
  416. {
  417.     if (Via(Codes)->PendingLabel) {
  418.     Via(Via(Codes)->PendingLabel)->M68kDef.where = inst;
  419.     Via(Codes)->PendingLabel = NULL;
  420.     }
  421.     if (Via(inst)->OP == M68op_DATALABEL) {
  422.     Via(Codes)->PendingLabel = GetLocLabel(Via(inst)->left);
  423.     }
  424.     if (Via(inst)->OP == M68op_CODELABEL) {
  425.     Via(Codes)->PendingLabel = GetLocLabel(Via(inst)->left);
  426.     }
  427.     if (Via(inst)->OP == M68op_LABEL) {
  428.     Via(Codes)->PendingLabel = GetLocLabel(Via(inst)->left);
  429.     }
  430.     if (Via(inst)->OP == M68op_STRINGLABEL) {
  431.     Via(Codes)->PendingLabel = GetLocLabel(Via(inst)->left);
  432.     }
  433.     if (Via(Codes)->tail) {
  434.     Via(Via(Codes)->tail)->next = inst;
  435.     Via(inst)->prev = Via(Codes)->tail;
  436.     Via(Codes)->tail = inst;
  437.     Via(Codes)->count++;
  438.     } else {
  439.     Via(Codes)->head = Via(Codes)->tail = inst;
  440.     Via(Codes)->count = 1;
  441.     }
  442. }
  443.  
  444. InstVia_t
  445. InsertInstruction(Opcode_t OP, enum Size68 SZ, LocAMVia_t left, LocAMVia_t right, InstVia_t after)
  446. {
  447.     /*
  448.      * Generate an instruction record and insert it after after.
  449.      */
  450.     InstVia_t                       inst;
  451.     inst = RawInstruction();
  452.     if (inst) {
  453.     Via(inst)->OP = OP;
  454.     Via(inst)->SZ = SZ;
  455.     Via(inst)->left = left;
  456.     Via(inst)->right = right;
  457.     Via(inst)->prev = after;
  458.     Via(inst)->next = Via(after)->next;
  459.     if (Via(after)->next) {
  460.         Via(Via(after)->next)->prev = inst;
  461.     }
  462.     Via(after)->next = inst;
  463.     }
  464.     return inst;
  465. }
  466.  
  467. InstVia_t
  468. GenInst(Opcode_t OP, enum Size68 SZ, LocAMVia_t left, LocAMVia_t right, InstListVia_t Codes)
  469. {
  470.     /*
  471.      * Generate an instruction record and insert it into Codes. This routine
  472.      * automatically checks to make sure that its operands are valid (ie -
  473.      * not spilled)
  474.      */
  475.     register InstVia_t              inst;
  476.     if (left) {
  477.     if (GetLocStatus(left) == M68os_spilled) {
  478.         left = ValidateReg(left, Codes);
  479.     }
  480.     }
  481.     if (right) {
  482.     assert(left);
  483.     if (GetLocStatus(right) == M68os_spilled) {
  484.         right = ValidateReg(right, Codes);
  485.     }
  486.     }
  487.     if (SZ == 0) {
  488.     Gen68Error("SZ = 0 in gen68_inst");
  489.     }
  490.     if (SZ > 4) {
  491.     Gen68Error("SZ > 4 in gen68_inst");
  492.     }
  493.     if (left) {
  494.     if (right) {
  495.         if ((GetLocAM(left) == M68am_FReg) && (GetLocAM(right) == M68am_FReg)) {
  496.         SZ = M68sz_extended;
  497.         }
  498.     } else {
  499.         if ((GetLocAM(left) == M68am_FReg)) {
  500.         SZ = M68sz_extended;
  501.         }
  502.     }
  503.     }
  504.     inst = RawInstruction();
  505.     if (inst) {
  506.     Via(inst)->OP = OP;
  507.     Via(inst)->SZ = SZ;
  508.     Via(inst)->left = left;
  509.     Via(inst)->right = right;
  510.     AddInstruction(inst, Codes);
  511.     }
  512.     return inst;
  513. }
  514.  
  515. void
  516. AddInstList(InstListVia_t list, InstListVia_t Codes)
  517. /* Adds all the contents of one instruction list to another. */
  518. {
  519.     InstVia_t                       inst;
  520.     if (list) {
  521.     inst = Via(list)->head;
  522.     while (inst) {
  523.         AddInstruction(inst, Codes);
  524.         inst = Via(inst)->next;
  525.     }
  526.     }
  527. }
  528.  
  529. void
  530. GenPush(LocAMVia_t loc, InstListVia_t Codes)
  531. /*
  532.  * Generates a push instruction, pushing the arg loc onto the stack.
  533.  */
  534. {
  535.     LocAMVia_t                      stkpush;
  536.     stkpush = RawLocation();
  537.     SetLocAM(stkpush, M68am_ARegPreDec);
  538.     SetLocAReg(stkpush, 7);
  539.     /*
  540.      * This special case should probably be unnecessary if the sizing code
  541.      * for doubles were really handled right.
  542.      */
  543.     if (GetLocSZ(loc) == M68sz_extended) {
  544.         Genmove(M68sz_double, loc, stkpush, Codes);
  545.     } else if (GetLocSZ(loc) == 1) {
  546.         /* Bytes are really pushed as words. */
  547.         /* This code should be unnecessary */
  548.         loc = DictateTempDReg(loc, Codes);
  549.         GenInst(M68op_EXT, M68sz_word, loc, NULL, Codes);
  550.         Genmove(M68sz_word, loc, stkpush, Codes);
  551.         FreeTemp(loc);
  552.     } else if (GetLocAM(loc) == M68am_FSANEtemp) {
  553.         /*
  554.          * This should be pushed as a double, or a float, but not as
  555.          * extended.
  556.          */
  557.         SpillSlotVia_t                  slot;
  558.         LocAMVia_t                      lop;
  559.         if (GetLocSZ(loc) == 4) {
  560.             slot = GetSpillSlot(4);
  561.             lop = Via(slot)->SlotLoc;
  562.             GenSANECall(FFSGL + FOX2Z, loc, lop, Codes);
  563.             GenInst(M68op_MOVE, M68sz_long, lop, stkpush, Codes);
  564.             FreeTemp(lop);
  565.         } else {
  566.             slot = GetSpillSlot(12);
  567.             lop = Via(slot)->SlotLoc;
  568.             GenSANECall(FFDBL + FOX2Z, loc, lop, Codes);
  569.             GenInst(M68op_MOVE, M68sz_long, BuildARegDisplace(GetLocAReg(lop), GetLocConstant(lop) + 4), stkpush, Codes);
  570.             GenInst(M68op_MOVE, M68sz_long, lop, stkpush, Codes);
  571.             FreeTemp(lop);
  572.         }
  573.     } else {
  574.         Genmove(GetLocSZ(loc), loc, stkpush, Codes);
  575.     }
  576. }
  577.  
  578. void
  579. GenPascalPush(LocAMVia_t loc, InstListVia_t Codes)
  580. /*
  581.  * Generates a push instruction, pushing the arg loc onto the stack.
  582.  */
  583. {
  584.     LocAMVia_t                      stkpush;
  585.     stkpush = RawLocation();
  586.     SetLocAM(stkpush, M68am_ARegPreDec);
  587.     SetLocAReg(stkpush, 7);
  588.     /*
  589.      * This special case should probably be unnecessary if the sizing code
  590.      * for doubles were really handled right.
  591.      */
  592.     if (GetLocSZ(loc) == M68sz_extended) {
  593.         Genmove(M68sz_double, loc, stkpush, Codes);
  594.     } else if (GetLocSZ(loc) == 1) {
  595.         Genmove(M68sz_byte, loc, stkpush, Codes);
  596.     } else if (GetLocAM(loc) == M68am_FSANEtemp) {
  597.         /*
  598.          * This should be pushed as a double, or a float, but not as
  599.          * extended.
  600.          */
  601.         SpillSlotVia_t                  slot;
  602.         LocAMVia_t                      lop;
  603.         if (GetLocSZ(loc) == 4) {
  604.             slot = GetSpillSlot(4);
  605.             lop = Via(slot)->SlotLoc;
  606.             GenSANECall(FFSGL + FOX2Z, loc, lop, Codes);
  607.             GenInst(M68op_MOVE, M68sz_long, lop, stkpush, Codes);
  608.             FreeTemp(lop);
  609.         } else {
  610.             slot = GetSpillSlot(12);
  611.             lop = Via(slot)->SlotLoc;
  612.             GenSANECall(FFDBL + FOX2Z, loc, lop, Codes);
  613.             GenInst(M68op_MOVE, M68sz_long, BuildARegDisplace(GetLocAReg(lop), GetLocConstant(lop) + 4), stkpush, Codes);
  614.             GenInst(M68op_MOVE, M68sz_long, lop, stkpush, Codes);
  615.             FreeTemp(lop);
  616.         }
  617.     } else {
  618.         Genmove(GetLocSZ(loc), loc, stkpush, Codes);
  619.     }
  620. }
  621.  
  622. void
  623. GenCodeLabel(LabSYMVia_t labsym, InstListVia_t Codes)
  624. /* Generates a label marking the beginning of a code module */
  625. {
  626.     GenInst(M68op_MPWSEG, M68sz_none, BuildLabelLoc(NextFuncSegment), NULL, Codes);
  627.     GenInst(M68op_CODELABEL, M68sz_none, BuildLabelLoc(labsym), NULL, Codes);
  628. }
  629.  
  630. void
  631. GenDataLabel(LabSYMVia_t labsym, InstListVia_t Codes)
  632. /* Generates a label marking the beginning of a data module */
  633. {
  634.     GenInst(M68op_DATALABEL, M68sz_none,
  635.         BuildLabelLoc(labsym), NULL, Codes);
  636. }
  637.  
  638. void
  639. GenStringLabel(LabSYMVia_t labsym, InstListVia_t Codes)
  640. /* Generates a label marking the beginning of a string lit */
  641. {
  642.     GenInst(M68op_STRINGLABEL, M68sz_none,
  643.         BuildLabelLoc(labsym), NULL, Codes);
  644. }
  645.  
  646. void
  647. GenLabel(LabSYMVia_t labsym, InstListVia_t Codes)
  648. /* Shorter call for generating a label instruction. */
  649. {
  650.     GenInst(M68op_LABEL, M68sz_none,
  651.         BuildLabelLoc(labsym), NULL, Codes);
  652. }
  653.  
  654. void
  655. ShiftRight(LocAMVia_t loc, int shifts, InstListVia_t Codes)
  656. /*
  657.  * Used in bit fields, generates code to shift the given loc to the right
  658.  */
  659. {
  660.     if (shifts > 0) {
  661.     int                             leftover;
  662.     leftover = shifts;
  663.     while (leftover) {
  664.         if (leftover > 7) {
  665.         GenInst(M68op_LSR, M68sz_long, BuildImmediate(7, M68sz_long), loc, Codes);
  666.         leftover -= 7;
  667.         } else {
  668.         GenInst(M68op_LSR, M68sz_long, BuildImmediate(leftover, M68sz_long), loc, Codes);
  669.         leftover = 0;
  670.         }
  671.     }
  672.     }
  673. }
  674.  
  675. void
  676. ShiftLeft(LocAMVia_t loc, int shifts, InstListVia_t Codes)
  677. /*
  678.  * Used in bit fields, generates code to shift the given loc to the left
  679.  */
  680. {
  681.     if (shifts > 0) {
  682.     int                             leftover;
  683.     leftover = shifts;
  684.     while (leftover) {
  685.         if (leftover > 7) {
  686.         GenInst(M68op_LSL, M68sz_long, BuildImmediate(7, M68sz_long), loc, Codes);
  687.         leftover -= 7;
  688.         } else {
  689.         GenInst(M68op_LSL, M68sz_long, BuildImmediate(leftover, M68sz_long), loc, Codes);
  690.         leftover = 0;
  691.         }
  692.     }
  693.     }
  694. }
  695.  
  696. unsigned long
  697. MakeTheMask(int lo, int hi)
  698. {
  699.     /* Construct a mask - used in generating code for bitfields */
  700.     unsigned long                   bitmask;
  701.     int                             ndx;
  702.     bitmask = 0;
  703.     ndx = lo;
  704.     while (ndx <= hi) {
  705.     bitmask |= ((unsigned long) 1) << ndx;
  706.     ndx++;
  707.     }
  708.     return bitmask;
  709. }
  710.  
  711. unsigned long
  712. MakeMask(LocAMVia_t loc)
  713. /* Used in generating code for bitfields */
  714. {
  715.     return MakeTheMask(GetLocFieldBits(loc).StartBit, GetLocFieldBits(loc).EndBit);
  716. }
  717.  
  718. void
  719. GenDeConflictize(LocAMVia_t * a, LocAMVia_t * b, InstListVia_t Codes)
  720. {
  721.     /*
  722.      * Given two locs, modify them as necessary to ensure that they are not
  723.      * in conflict.  In other words, ensure that the register allocator did
  724.      * not assign the same register to both.  If so, one will be moved.
  725.      */
  726.     LocAMVia_t                      c;
  727.     LocAMVia_t                      d;
  728.     LocAMVia_t                      newhome;
  729.     if (a && b) {
  730.     c = *a;
  731.     d = *b;
  732.     if (c && d) {
  733.         if (c == d)
  734.         return;
  735.         if (!(isTempReg(c) && isTempReg(d)))
  736.         return;
  737.         if (GetLocAM(c) == M68am_DReg) {
  738.         if (GetLocAM(d) == M68am_DReg) {
  739.             if (GetLocDReg(c) == GetLocDReg(d)) {
  740.             /*
  741.              * Conflict detected.  One of these if spilled - we
  742.              * move the other one to another register.
  743.              */
  744.             if (GetLocStatus(d) == M68os_valid) {
  745.                 newhome = TempDataReg(Codes);
  746.                 Genmove(M68sz_long, d, newhome, Codes);
  747.                 SetLocSZ(newhome, GetLocSZ(d));
  748.                 FreeTemp(d);
  749.                 *b = newhome;
  750.                 return;
  751.             } else {
  752.                 newhome = TempDataReg(Codes);
  753.                 Genmove(M68sz_long, c, newhome, Codes);
  754.                 SetLocSZ(newhome, GetLocSZ(c));
  755.                 FreeTemp(c);
  756.                 *a = newhome;
  757.                 return;
  758.             }
  759.             } else
  760.             return;
  761.         } else
  762.             return;
  763.         } else if (isARegMode(c)) {
  764.         if (isARegMode(d)) {
  765.             if (GetLocAReg(c) == GetLocAReg(d)) {
  766.             if (GetLocStatus(c) == M68os_valid) {
  767.                 newhome = TempAddrReg(Codes);
  768.                 SetLocAM(newhome, GetLocAM(c));
  769.                 SetLocSZ(newhome, GetLocSZ(c));
  770.                 Genmove(M68sz_long, BuildARegDirect(GetLocAReg(c)),
  771.                    BuildARegDirect(GetLocAReg(newhome)), Codes);
  772.                 FreeTemp(c);
  773.                 *a = newhome;
  774.                 return;
  775.             } else {
  776.                 newhome = TempAddrReg(Codes);
  777.                 SetLocAM(newhome, GetLocAM(d));
  778.                 SetLocSZ(newhome, GetLocSZ(d));
  779.                 Genmove(M68sz_long, BuildARegDirect(GetLocAReg(d)),
  780.                    BuildARegDirect(GetLocAReg(newhome)), Codes);
  781.                 FreeTemp(d);
  782.                 *b = newhome;
  783.                 return;
  784.             }
  785.             } else
  786.             return;
  787.         } else
  788.             return;
  789.         } else
  790.         return;
  791.     }
  792.     }
  793. }
  794.  
  795. LocAMVia_t
  796. Slotify(LocAMVia_t loc, InstListVia_t Codes)
  797. /* Given a loc, move it to a spill slot */
  798. {
  799.     SpillSlotVia_t                  slot;
  800.     LocAMVia_t                      result;
  801.     slot = GetSpillSlot(GetLocSZ(loc));
  802.     result = Via(slot)->SlotLoc;
  803.     Genmove(GetLocSZ(result), loc, result, Codes);
  804.     FreeTemp(loc);
  805.     return result;
  806. }
  807.  
  808. int
  809. PushBackwards(ParseTreeVia_t arg, ParamRecVia_t Param, int *pcount, InstListVia_t Codes)
  810. {
  811. /* This function is used for calling pascal functions */
  812.     int                             result;
  813.     LocAMVia_t                      argop;
  814.     int                             done;
  815.     result = 0;
  816.     done = 0;
  817.     if (arg) {
  818.     if (Via(arg)->kind == PTF_argument_list) {
  819.         result = PushBackwards(Via(arg)->b, Param, pcount, Codes);
  820.         argop = GenExpression(Via(arg)->a, Codes);
  821.         if (!gProject->itsOptions->useMC68881)
  822.             SetLocSZ(argop, GetTPSize(GetTreeTP(Via(arg)->a)));
  823.         if (Param) {
  824.             if (*pcount < Via(Param)->argcount) {
  825.                 GenInst(M68op_MOVE, GetLocSZ(argop), argop, ParamLoc(Via(Param)->args[*pcount]), Codes);
  826.                 (*pcount)++;
  827.             } else
  828.                 GenPascalPush(argop, Codes);
  829.         } else
  830.             GenPascalPush(argop, Codes);
  831.         FreeTemp(argop);
  832.         result += GetTPSize(GetTreeTP(Via(arg)->a));
  833.         if (GetLocSZ(argop) == M68sz_byte) {
  834.             /* bytes are really pushed as words. */
  835.             result++;
  836.         }
  837.     } else {
  838.         /* Last arg to be pushed. */
  839.         done = 1;
  840.         argop = GenExpression(arg, Codes);
  841.         if (!gProject->itsOptions->useMC68881)
  842.             SetLocSZ(argop, GetTPSize(GetTreeTP(arg)));
  843.         if (Param) {
  844.             if (*pcount < Via(Param)->argcount) {
  845.                 GenInst(M68op_MOVE, GetLocSZ(argop), argop, ParamLoc(Via(Param)->args[*pcount]), Codes);
  846.                 (*pcount)++;
  847.             } else
  848.                 GenPascalPush(argop, Codes);
  849.         } else
  850.             GenPascalPush(argop, Codes);
  851.         FreeTemp(argop);
  852.         result = GetTPSize(GetTreeTP(arg));
  853.         if (GetLocSZ(argop) == M68sz_byte) {
  854.             /* bytes are really pushed as words. */
  855.             result++;
  856.         }
  857.     }
  858.     }
  859.     return result;
  860. }
  861.  
  862. int
  863. PushArguments(ParseTreeVia_t fcallnode, int ispascal, ParamRecVia_t Param, InstListVia_t Codes)
  864. /*
  865.  * Given a list of arguments to a function, push them onto the stack. The
  866.  * argument expressions are evaluated before pushing them.  Push pascal
  867.  * arguments backwards.
  868.  */
  869. {
  870.     int                             result;
  871.     int                             pcount;
  872.     int                             argsleft = 0;
  873.     int                             paramsleft = 0;
  874.     ParseTreeVia_t                  arg;
  875.     LocAMVia_t                      argop;
  876.     LocAMVia_t                      temparg;
  877.     int                             done;
  878.     result = 0;
  879.     done = 0;
  880.     /*
  881.      * For each argument, generate code for the expression, pushing the
  882.      * result on the stack.
  883.      */
  884.     arg = Via(fcallnode)->b;
  885.     if (ispascal) {
  886.     pcount = 0;
  887.     result = PushBackwards(arg, Param, &pcount, Codes);
  888.     } else {
  889.     if (Param) {
  890.         paramsleft = Via(Param)->argcount;
  891.         argsleft = CountArgs(arg);
  892.     }
  893.     while ((!done) && arg) {
  894.         if (Via(arg)->kind == PTF_argument_list) {
  895.         argop = GenExpression(Via(arg)->a, Codes);
  896.         if (!gProject->itsOptions->useMC68881)
  897.             SetLocSZ(argop, GetTPSize(GetTreeTP(Via(arg)->a)));
  898.         if (GetLocSZ(argop) == M68sz_byte) {
  899.             temparg = TempDataReg(Codes);
  900.             GenInst(M68op_MOVE, GetLocSZ(argop), argop, temparg, Codes);
  901.             FreeTemp(argop);
  902.             GenInst(M68op_EXT, M68sz_word, temparg, NULL, Codes);
  903.             GenInst(M68op_EXT, M68sz_long, temparg, NULL, Codes);
  904.             SetLocSZ(temparg, M68sz_long);
  905.             argop = temparg;
  906.         }
  907.         if (GetLocSZ(argop) == M68sz_word) {
  908.             temparg = TempDataReg(Codes);
  909.             GenInst(M68op_MOVE, GetLocSZ(argop), argop, temparg, Codes);
  910.             FreeTemp(argop);
  911.             GenInst(M68op_EXT, M68sz_long, temparg, NULL, Codes);
  912.             SetLocSZ(temparg, M68sz_long);
  913.             argop = temparg;
  914.         }
  915.         if (paramsleft && (argsleft <= paramsleft)) {
  916.             if (argsleft < paramsleft)
  917.             paramsleft = argsleft;
  918.             GenInst(M68op_MOVE, GetLocSZ(argop), argop, ParamLoc(Via(Param)->args[paramsleft - 1]), Codes);
  919.             paramsleft--;
  920.         } else
  921.             GenPush(argop, Codes);
  922.         argsleft--;
  923.         FreeTemp(argop);
  924.         result += GetTPSize(GetTreeTP(Via(arg)->a));
  925.         if (GetTPSize(GetTreeTP(Via(arg)->a)) == 1) {
  926.             /* bytes are really pushed as longs. */
  927.             result += 3;
  928.         }
  929.         if (GetTPSize(GetTreeTP(Via(arg)->a)) == 2) {
  930.             /* shorts are really pushed as longs. */
  931.             result += 2;
  932.         }
  933.         arg = Via(arg)->b;
  934.         } else {
  935.         /* Last arg to be pushed. */
  936.         done = 1;
  937.         argop = GenExpression(arg, Codes);
  938.         if (!gProject->itsOptions->useMC68881)
  939.             SetLocSZ(argop, GetTPSize(GetTreeTP(arg)));
  940.         if (GetLocSZ(argop) == M68sz_byte) {
  941.             temparg = TempDataReg(Codes);
  942.             GenInst(M68op_MOVE, GetLocSZ(argop), argop, temparg, Codes);
  943.             FreeTemp(argop);
  944.             GenInst(M68op_EXT, M68sz_word, temparg, NULL, Codes);
  945.             GenInst(M68op_EXT, M68sz_long, temparg, NULL, Codes);
  946.             SetLocSZ(temparg, M68sz_long);
  947.             argop = temparg;
  948.         }
  949.         if (GetLocSZ(argop) == M68sz_word) {
  950.             temparg = TempDataReg(Codes);
  951.             GenInst(M68op_MOVE, GetLocSZ(argop), argop, temparg, Codes);
  952.             FreeTemp(argop);
  953.             GenInst(M68op_EXT, M68sz_long, temparg, NULL, Codes);
  954.             SetLocSZ(temparg, M68sz_long);
  955.             argop = temparg;
  956.         }
  957.         if (paramsleft && (argsleft <= paramsleft)) {
  958.             if (argsleft < paramsleft)
  959.             paramsleft = argsleft;
  960.             GenInst(M68op_MOVE, GetLocSZ(argop), argop, ParamLoc(Via(Param)->args[paramsleft - 1]), Codes);
  961.             paramsleft--;
  962.         } else
  963.             GenPush(argop, Codes);
  964.         argsleft--;
  965.         FreeTemp(argop);
  966.         result += GetTPSize(GetTreeTP(arg));
  967.         if (GetTPSize(GetTreeTP(arg)) == 1) {
  968.             /* bytes are really pushed as longs. */
  969.             result += 3;
  970.         }
  971.         if (GetTPSize(GetTreeTP(arg)) == 2) {
  972.             /* short are really pushed as longs. */
  973.             result += 2;
  974.         }
  975.         }
  976.     }
  977.     }
  978.     return result;
  979. }
  980.  
  981. void
  982. GenCompareBranch2(LocAMVia_t leftop, ParseTreeVia_t right,
  983.           Opcode_t OP, LabSYMVia_t label,
  984.           InstListVia_t Codes)
  985. {
  986.     /* leftop must be a temporary.  If non float, it must be in a dreg */
  987.     /*
  988.      * Used for switch comparisons, so the control expression need be
  989.      * evaluated only once.
  990.      */
  991.  
  992.     LocAMVia_t                      rightop;
  993.     if (isFloatingType(GetTreeTP(right))) {
  994.     rightop = GenExpression(right, Codes);
  995.     if (gProject->itsOptions->useMC68881) {
  996.         GenInst(M68op_FCMP, GetLocSZ(rightop), rightop, leftop, Codes);
  997.         switch (OP) {
  998.         case M68op_BEQ:
  999.         OP = M68op_FBEQ;
  1000.         break;
  1001.         case M68op_BNE:
  1002.         OP = M68op_FBNE;
  1003.         break;
  1004.         case M68op_BLT:
  1005.         OP = M68op_FBLT;
  1006.         break;
  1007.         case M68op_BGT:
  1008.         OP = M68op_FBGT;
  1009.         break;
  1010.         case M68op_BLE:
  1011.         OP = M68op_FBLE;
  1012.         break;
  1013.         case M68op_BGE:
  1014.         OP = M68op_FBGE;
  1015.         break;
  1016.         }
  1017.         GenInst(OP, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1018.     } else {
  1019.         rightop = DictateTempFloat(rightop, Codes);
  1020.         GenSANECall(FFEXT + FOCMP, rightop, leftop, Codes);
  1021.         switch (OP) {
  1022.         case M68op_BEQ:
  1023.         OP = M68op_BEQ;
  1024.         break;
  1025.         case M68op_BNE:
  1026.         OP = M68op_BNE;
  1027.         break;
  1028.         case M68op_BLT:
  1029.         OP = M68op_BCS;
  1030.         break;
  1031.         case M68op_BGT:
  1032.         OP = M68op_BGT;
  1033.         break;
  1034.         case M68op_BLE:
  1035.         OP = M68op_BLS;
  1036.         break;
  1037.         case M68op_BGE:
  1038.         OP = M68op_BGE;
  1039.         break;
  1040.         }
  1041.         GenInst(OP, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1042.     }
  1043.     FreeTemp(rightop);
  1044.     FreeTemp(leftop);
  1045.     } else {
  1046.     rightop = GenExpression(right, Codes);
  1047.     GenInst(M68op_CMP, GetLocSZ(leftop), rightop, leftop, Codes);
  1048.     GenInst(OP, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1049.     FreeTemp(rightop);
  1050.     }
  1051. }
  1052.  
  1053. void
  1054. GenCompareBranch(ParseTreeVia_t left, ParseTreeVia_t right,
  1055.          Opcode_t OP, LabSYMVia_t label,
  1056.          InstListVia_t Codes)
  1057. {
  1058.     /*
  1059.      * Compares the two expressions, generating a branch (contained in the OP
  1060.      * arg) afterwards.
  1061.      */
  1062.     LocAMVia_t                      leftop;
  1063.     LocAMVia_t                      rightop;
  1064.     if (isFloatingType(GetTreeTP(left))) {
  1065.     leftop = GenExpression(left, Codes);
  1066.     leftop = DictateTempFloat(leftop, Codes);
  1067.     rightop = GenExpression(right, Codes);
  1068.     if (gProject->itsOptions->useMC68881) {
  1069.         GenInst(M68op_FCMP, GetLocSZ(rightop), rightop, leftop, Codes);
  1070.         switch (OP) {
  1071.         case M68op_BEQ:
  1072.         OP = M68op_FBEQ;
  1073.         break;
  1074.         case M68op_BNE:
  1075.         OP = M68op_FBNE;
  1076.         break;
  1077.         case M68op_BLT:
  1078.         OP = M68op_FBLT;
  1079.         break;
  1080.         case M68op_BGT:
  1081.         OP = M68op_FBGT;
  1082.         break;
  1083.         case M68op_BLE:
  1084.         OP = M68op_FBLE;
  1085.         break;
  1086.         case M68op_BGE:
  1087.         OP = M68op_FBGE;
  1088.         break;
  1089.         }
  1090.         GenInst(OP, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1091.     } else {
  1092.         rightop = DictateTempFloat(rightop, Codes);
  1093.         GenSANECall(FFEXT + FOCMP, rightop, leftop, Codes);
  1094.         switch (OP) {
  1095.         case M68op_BEQ:
  1096.         OP = M68op_BEQ;
  1097.         break;
  1098.         case M68op_BNE:
  1099.         OP = M68op_BNE;
  1100.         break;
  1101.         case M68op_BLT:
  1102.         OP = M68op_BCS;
  1103.         break;
  1104.         case M68op_BGT:
  1105.         OP = M68op_BGT;
  1106.         break;
  1107.         case M68op_BLE:
  1108.         OP = M68op_BLS;
  1109.         break;
  1110.         case M68op_BGE:
  1111.         OP = M68op_BGE;
  1112.         break;
  1113.         }
  1114.         GenInst(OP, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1115.     }
  1116.     FreeTemp(rightop);
  1117.     FreeTemp(leftop);
  1118.     } else {
  1119.     if (isUnsignedType(GetTreeTP(left))) {
  1120.         leftop = GenExpression(left, Codes);
  1121.         rightop = GenExpression(right, Codes);
  1122.         leftop = DictateAnyDReg(leftop, Codes);
  1123.         GenInst(M68op_CMP, GetLocSZ(leftop), rightop, leftop, Codes);
  1124.         switch (OP) {
  1125.         case M68op_BLT:
  1126.         OP = M68op_BCS;
  1127.         break;
  1128.         case M68op_BGT:
  1129.         OP = M68op_BHI;
  1130.         break;
  1131.         case M68op_BLE:
  1132.         OP = M68op_BLS;
  1133.         break;
  1134.         case M68op_BGE:
  1135.         OP = M68op_BCC;
  1136.         break;
  1137.         }
  1138.         GenInst(OP, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1139.         FreeTemp(rightop);
  1140.         FreeTemp(leftop);
  1141.     } else {
  1142.         leftop = GenExpression(left, Codes);
  1143.         rightop = GenExpression(right, Codes);
  1144.         /*
  1145.          * TODO Here would be a good usage of the extended reg allocator
  1146.          * which would allow specification of a noconflict loc
  1147.          */
  1148.         leftop = DictateAnyDReg(leftop, Codes);
  1149.         GenDeConflictize(&leftop, &rightop, Codes);
  1150.         GenInst(M68op_CMP, GetLocSZ(leftop), rightop, leftop, Codes);
  1151.         GenInst(OP, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1152.         FreeTemp(rightop);
  1153.         FreeTemp(leftop);
  1154.     }
  1155.     }
  1156. }
  1157.  
  1158. void
  1159. GenCompareZero(ParseTreeVia_t expr, LabSYMVia_t label,
  1160.            InstListVia_t Codes)
  1161. {
  1162.     /*
  1163.      * Compares the given expression with 0, and branches to the given label
  1164.      * if the expression is zero.
  1165.      */
  1166.  
  1167.     ParseTreeVia_t                  zeroexpr;
  1168.     FoldValue_t                     testK;
  1169.     if (!expr) {
  1170.         GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1171.         return;
  1172.     }
  1173.     ConstExprValue(expr, &testK);
  1174.     if (testK.isK) {
  1175.     if (testK.isint) {
  1176.         if (testK.intval) {
  1177.         return;
  1178.         } else {
  1179.         GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1180.         return;
  1181.         }
  1182.     }
  1183.     }
  1184.     /*
  1185.      * First we build a parse tree node equal to constant zero, so we can
  1186.      * compare the argument with it.
  1187.      */
  1188.     zeroexpr = BuildTreeNode(PTF_intconstant, NULL, NULL, NULL);
  1189.     SetTreeTP(zeroexpr, GetTreeTP(expr));
  1190.     Via(zeroexpr)->data.number = 0;
  1191.     if (isFloatingType(GetTreeTP(expr))) {
  1192.         SetTreeTP(zeroexpr, BuildTypeRecord(0, TRC_int, SGN_signed));
  1193.         zeroexpr = TypeConvert(zeroexpr, BuildTypeRecord(0, TRC_longdouble,
  1194.                                  SGN_unknown));
  1195.     }
  1196.     /*
  1197.      * In certain cases here, we can simply reverse the direction of the
  1198.      * branch which would normally be generated by the boolean expression in
  1199.      * expr, and branch instead to the label passed here, instead of
  1200.      * generating the intermediate boolean value of 0 or 1.
  1201.      */
  1202.     if (isIntegralType(GetTreeTP(expr)) && !isUnsignedType(GetTreeTP(expr))) {
  1203.     switch (Via(expr)->kind) {
  1204.     case PTF_lessthan:
  1205.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BGE, label, Codes);
  1206.         break;
  1207.     case PTF_greaterthan:
  1208.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BLE, label, Codes);
  1209.         break;
  1210.     case PTF_lessthaneq:
  1211.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BGT, label, Codes);
  1212.         break;
  1213.     case PTF_greaterthaneq:
  1214.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BLT, label, Codes);
  1215.         break;
  1216.     case PTF_equal:
  1217.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BNE, label, Codes);
  1218.         break;
  1219.     case PTF_notequal:
  1220.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BEQ, label, Codes);
  1221.         break;
  1222.     default:
  1223.         GenCompareBranch(expr, zeroexpr, M68op_BEQ, label, Codes);
  1224.         break;
  1225.     }
  1226.     } else {
  1227.         GenCompareBranch(expr, zeroexpr, M68op_BEQ, label, Codes);
  1228.     }
  1229.     FreeTree(zeroexpr);
  1230. }
  1231.  
  1232. void
  1233. GenCompareNonZero(ParseTreeVia_t expr,
  1234.           LabSYMVia_t label,
  1235.           InstListVia_t Codes)
  1236. {
  1237.     /*
  1238.      * Compares the given expression with 0, and branches to the given label
  1239.      * if the expression is non-zero.
  1240.      */
  1241.  
  1242.     ParseTreeVia_t                  zeroexpr;
  1243.     FoldValue_t                     testK;
  1244.     if (!expr)
  1245.     return;
  1246.     ConstExprValue(expr, &testK);
  1247.     if (testK.isK) {
  1248.     if (testK.isint) {
  1249.         if (testK.intval) {
  1250.         GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(label), NULL, Codes);
  1251.         return;
  1252.         } else {
  1253.         return;
  1254.         }
  1255.     }
  1256.     }
  1257.     zeroexpr = BuildTreeNode(PTF_intconstant, NULL, NULL, NULL);
  1258.     SetTreeTP(zeroexpr, GetTreeTP(expr));
  1259.     Via(zeroexpr)->data.number = 0;
  1260.     if (isFloatingType(GetTreeTP(expr))) {
  1261.     SetTreeTP(zeroexpr, BuildTypeRecord(0, TRC_int, SGN_signed));
  1262.     zeroexpr = TypeConvert(zeroexpr, BuildTypeRecord(0, TRC_longdouble,
  1263.                              SGN_unknown));
  1264.     }
  1265.     /*
  1266.      * In certain cases here, we can simply reverse the direction of the
  1267.      * branch which would normally be generated by the boolean expression in
  1268.      * expr, and branch instead to the label passed here, instead of
  1269.      * generating the intermediate boolean value of 0 or 1.
  1270.      */
  1271.     if (isIntegralType(GetTreeTP(expr)) && !isUnsignedType(GetTreeTP(expr))) {
  1272.     switch (Via(expr)->kind) {
  1273.     case PTF_lessthan:
  1274.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BLT, label, Codes);
  1275.         break;
  1276.     case PTF_greaterthan:
  1277.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BGT, label, Codes);
  1278.         break;
  1279.     case PTF_lessthaneq:
  1280.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BLE, label, Codes);
  1281.         break;
  1282.     case PTF_greaterthaneq:
  1283.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BGE, label, Codes);
  1284.         break;
  1285.     case PTF_equal:
  1286.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BEQ, label, Codes);
  1287.         break;
  1288.     case PTF_notequal:
  1289.         GenCompareBranch(Via(expr)->a, Via(expr)->b, M68op_BNE, label, Codes);
  1290.         break;
  1291.     default:
  1292.         GenCompareBranch(expr, zeroexpr, M68op_BNE, label, Codes);
  1293.         break;
  1294.     }
  1295.     } else {
  1296.     GenCompareBranch(expr, zeroexpr, M68op_BNE, label, Codes);
  1297.     }
  1298.     FreeTree(zeroexpr);
  1299. }
  1300.  
  1301. LocAMVia_t
  1302. GenLibraryCall(LocAMVia_t leftop, LocAMVia_t rightop,
  1303.            LabSYMVia_t label, InstListVia_t Codes)
  1304. {
  1305.     /*
  1306.      * Generate a call to the long math library. Arguments are the two
  1307.      * operands and the label of the library routine being called.
  1308.      */
  1309.     LocAMVia_t                      result;
  1310.     SaveTheRegisters(Codes);    // Changed from SaveDataRegisters() 24 Mar 1992
  1311.     /*
  1312.      * The code below is designed to ensure that nothing gets validated in
  1313.      * the process of filling d0 and 1.  The size of the move is always long
  1314.      * because a reg is always spilled as long and the destination is always
  1315.      * long.  QQQQ Should we ensure that the destination dreg is zeroed just
  1316.      * in case of a byte or word operand, when not dealing with spilled ops ?
  1317.      */
  1318.     if (!((GetLocAM(leftop) == M68am_DReg) && (GetLocDReg(leftop) == 0))) {
  1319.     if ((GetLocAM(leftop) == M68am_DReg) && (GetLocStatus(leftop) == M68os_spilled)) {
  1320.         Genmove(M68sz_long, Via(GetLocSlot(leftop))->SlotLoc, BuildDRegLocation(0), Codes);
  1321.     } else {
  1322.         Genmove(GetLocSZ(leftop), leftop, BuildDRegLocation(0), Codes);
  1323.     }
  1324.     }
  1325.     if (!((GetLocAM(rightop) == M68am_DReg) && (GetLocDReg(rightop) == 1))) {
  1326.     if ((GetLocAM(rightop) == M68am_DReg) && (GetLocStatus(rightop) == M68os_spilled)) {
  1327.         Genmove(M68sz_long, Via(GetLocSlot(rightop))->SlotLoc, BuildDRegLocation(1), Codes);
  1328.     } else {
  1329.         Genmove(GetLocSZ(rightop), rightop, BuildDRegLocation(1), Codes);
  1330.     }
  1331.     }
  1332.     GenInst(M68op_JSR, M68sz_none,
  1333.           BuildARegLabelDisplace(5, label), NULL, Codes);
  1334.     /*
  1335.      * We allocate a spill slot to return the result.  The whole library call
  1336.      * should not disturb the register allocation situation at all.
  1337.      */
  1338. #define IWISH
  1339. #ifdef IWISH
  1340.     result = TempDataReg(Codes);
  1341.     if (GetLocDReg(result) != 0) {
  1342.     Genmove(M68sz_long, BuildDRegLocation(0), result, Codes);
  1343.     }
  1344.     SetLocSZ(result, M68sz_long);
  1345. #else
  1346.     {
  1347.     SpillSlotVia_t                  slot;
  1348.     slot = GetSpillSlot(4);
  1349.     result = Via(slot)->SlotLoc;
  1350.     Genmove(M68sz_long, BuildDRegLocation(0), result, Codes);
  1351.     SetLocSZ(result, M68sz_long);
  1352.     }
  1353. #endif
  1354.     FreeTemp(leftop);
  1355.     FreeTemp(rightop);
  1356.     return result;
  1357. }
  1358.  
  1359. LocAMVia_t
  1360. GenMulUnsigned(Opcode_t OP, LocAMVia_t leftop, LocAMVia_t rightop,
  1361.            InstListVia_t Codes)
  1362. {
  1363.     /*
  1364.      * General routine to generate an unsigned multiply of two integers.
  1365.      * Depending on the current compilation options, generated code may vary.
  1366.      */
  1367.     if (GetLocSZ(leftop) > 2) {
  1368.     if (!gProject->itsOptions->useMC68020) {
  1369.         switch (OP) {
  1370.         case M68op_MULS:
  1371.         leftop = GenLibraryCall(leftop, rightop,
  1372.                     LibLabelULMULT, Codes);
  1373.         break;
  1374.         case M68op_DIVS:
  1375.         leftop = GenLibraryCall(leftop, rightop,
  1376.                     LibLabelULDIVT, Codes);
  1377.         break;
  1378.         }
  1379.     } else {
  1380.         leftop = DictateTempDReg(leftop, Codes);
  1381.         GenDeConflictize(&leftop, &rightop, Codes);
  1382.         switch (OP) {
  1383.         case M68op_MULS:
  1384.         GenInst(M68op_MULU, M68sz_long, rightop, leftop, Codes);
  1385.         break;
  1386.         case M68op_DIVS:
  1387.         GenInst(M68op_DIVU, M68sz_long, rightop, leftop, Codes);
  1388.         break;
  1389.         }
  1390.     }
  1391.     } else {
  1392.     leftop = DictateTempDReg(leftop, Codes);
  1393.     rightop = DictateTempDReg(rightop, Codes);
  1394.     GenDeConflictize(&leftop, &rightop, Codes);
  1395.     switch (OP) {
  1396.     case M68op_MULS:
  1397.         GenInst(M68op_MULU, M68sz_none, rightop, leftop, Codes);
  1398.         break;
  1399.     case M68op_DIVS:
  1400.         GenInst(M68op_DIVU, M68sz_none, rightop, leftop, Codes);
  1401.         break;
  1402.     }
  1403.     }
  1404.     return leftop;
  1405. }
  1406.  
  1407. LocAMVia_t
  1408. GenMulSigned(Opcode_t OP, LocAMVia_t leftop, LocAMVia_t rightop,
  1409.          InstListVia_t Codes)
  1410. /*
  1411.  * General routine to generate an signed multiply of two integers. Depending
  1412.  * on the current compilation options, generated code may vary.
  1413.  */
  1414. {
  1415.     if (GetLocSZ(leftop) > 2) {
  1416.     if (!gProject->itsOptions->useMC68020) {
  1417.         switch (OP) {
  1418.         case M68op_MULS:
  1419.         leftop = GenLibraryCall(leftop, rightop,
  1420.                     LibLabelULMULT, Codes);
  1421.         break;
  1422.         case M68op_DIVS:
  1423.         leftop = GenLibraryCall(leftop, rightop,
  1424.                     LibLabelLDIVT, Codes);
  1425.         break;
  1426.         }
  1427.     } else {
  1428.         leftop = DictateTempDReg(leftop, Codes);
  1429.         GenInst(OP, M68sz_long, rightop, leftop, Codes);
  1430.     }
  1431.     } else {
  1432.     leftop = DictateTempDReg(leftop, Codes);
  1433.     rightop = DictateTempDReg(rightop, Codes);
  1434.     GenDeConflictize(&leftop, &rightop, Codes);
  1435.     GenInst(OP, M68sz_none, rightop, leftop, Codes);
  1436.     }
  1437.     return leftop;
  1438. }
  1439.  
  1440. int
  1441. isDRegMode(LocAMVia_t loc)
  1442. {
  1443.     if (loc) {
  1444.     switch (GetLocAM(loc)) {
  1445.         case M68am_DReg:
  1446.         return 1;
  1447.         break;
  1448.     default:
  1449.         return 0;
  1450.         break;
  1451.     }
  1452.     } else {
  1453.     return 0;
  1454.     }
  1455. }
  1456.  
  1457. int
  1458. isARegMode(LocAMVia_t loc)
  1459. {
  1460.     if (loc) {
  1461.     switch (GetLocAM(loc)) {
  1462.         case M68am_ARegDirect:
  1463.         case M68am_ARegIndirect:
  1464.         case M68am_ARegPostInc:
  1465.         case M68am_ARegPreDec:
  1466.         case M68am_ARegLabelDisplace:
  1467.         case M68am_ARegDisplace:
  1468.         case M68am_ARegDisplaceFIELD:
  1469.         case M68am_ARegDispIndx:
  1470.         return 1;
  1471.         break;
  1472.     default:
  1473.         return 0;
  1474.         break;
  1475.     }
  1476.     } else {
  1477.     return 0;
  1478.     }
  1479. }
  1480.  
  1481. LocAMVia_t
  1482. GenTypeChange(ParseTreeVia_t expr, InstListVia_t Codes)
  1483. /* This routine handles conversions between various types. */
  1484. {
  1485.     LocAMVia_t                      result = NULL;
  1486.     LocAMVia_t                      temploc;
  1487.     if (isFloatingType(GetTreeTP(expr))) {
  1488.     if (isIntegralType(GetTreeTP(Via(expr)->a))) {
  1489.         if (gProject->itsOptions->useMC68881) {
  1490.         temploc = GenExpression(Via(expr)->a, Codes);
  1491.         /*
  1492.          * We will assume that any expression which reaches here has
  1493.          * already been cast to long.
  1494.          */
  1495.         result = TempFloatReg(Codes);
  1496.         GenInst(M68op_FMOVE, GetLocSZ(temploc), temploc, result, Codes);
  1497.         } else {
  1498.         /*
  1499.          * We will assume that any expression which reaches here has
  1500.          * already been cast to long.
  1501.          */
  1502.         LocAMVia_t                      theint;
  1503.         LocAMVia_t                      ftemp;
  1504.         SpillSlotVia_t                  slot;
  1505.         ftemp = TempFloatReg(Codes);
  1506.         temploc = GenExpression(Via(expr)->a, Codes);
  1507.         slot = GetSpillSlot(M68sz_long);
  1508.         theint = Via(slot)->SlotLoc;
  1509.         SetLocSZ(theint, M68sz_long);
  1510.         GenInst(M68op_MOVE, M68sz_long, temploc, theint, Codes);
  1511.         FreeTemp(temploc);
  1512.         GenSANECall(FOZ2X + FFLNG, theint, ftemp, Codes);
  1513.         FreeTemp(theint);
  1514.         result = ftemp;
  1515.         /*
  1516.          * This routine ALWAYS converts its operand to SANE extended
  1517.          */
  1518.         }
  1519.     } else if (isFloatingType(GetTreeTP(Via(expr)->a))) {
  1520. #ifdef Undefined
  1521.         /* These will be different for Mac and SANE */
  1522.         if (isExtendedFloatingType(GetTreeTP(Via(expr)->a))) {
  1523.         result = GenExpression(Via(expr)->a, Codes);
  1524.         } else {
  1525.         if (!gProject->itsOptions->useMC68881) {
  1526.             LocAMVia_t                      ftemp;
  1527.             ftemp = TempFloatReg(Codes);
  1528.             result = GenExpression(Via(expr)->a, Codes);
  1529.             Genmove(GetLocSZ(result), result, ftemp, Codes);
  1530.             FreeTemp(result);
  1531.             result = ftemp;
  1532.         } else {
  1533.             if (GetTPKind(GetTreeTP(expr)) == TRC_float) {
  1534.             if (GetTPKind(GetTreeTP(Via(expr)->a)) != TRC_float) {
  1535.                 /* Convert double to float. */
  1536.                 LocAMVia_t                      temploc2;
  1537.                 SpillSlotVia_t                  slot;
  1538.                 temploc = GenExpression(Via(expr)->a, Codes);
  1539.                 temploc2 = TempFloatReg(Codes);
  1540.                 GenInst(M68op_FMOVE, GetLocSZ(temploc), temploc, temploc2, Codes);
  1541.                 Via(temploc2)->SZ = M68sz_single;
  1542.                 slot = GetSpillSlot(SizeOfFloat);
  1543.                 result = Via(slot)->SlotLoc;
  1544.                 SetLocSZ(result, M68sz_single);
  1545.                 GenInst(M68op_FMOVE, M68sz_single, temploc2, result, Codes);
  1546.                 FreeTemp(temploc2);
  1547.             } else {
  1548.                 result = GenExpression(Via(expr)->a, Codes);
  1549.                 SetLocSZ(result, M68sz_single);
  1550.             }
  1551.             } else if (GetTPKind(GetTreeTP(Via(expr)->a)) == TRC_float) {
  1552.             /* Convert float to double. */
  1553.             if (GetTPKind(GetTreeTP(expr)) != TRC_float) {
  1554.                 LocAMVia_t                      temploc2;
  1555.                 SpillSlotVia_t                  slot;
  1556.                 temploc = GenExpression(Via(expr)->a, Codes);
  1557.                 temploc2 = TempFloatReg(Codes);
  1558.                 GenInst(M68op_FMOVE, GetLocSZ(temploc), temploc, temploc2, Codes);
  1559.                 Via(temploc2)->SZ = M68sz_double;
  1560.                 slot = GetSpillSlot(SizeOfDouble);
  1561.                 result = Via(slot)->SlotLoc;
  1562.                 SetLocSZ(result, M68sz_double);
  1563.                 GenInst(M68op_FMOVE, M68sz_double, temploc2, result, Codes);
  1564.                 FreeTemp(temploc2);
  1565.             } else {
  1566.                 result = GenExpression(Via(expr)->a, Codes);
  1567.                 SetLocSZ(result, M68sz_single);
  1568.             }
  1569.             } else {
  1570.             result = GenExpression(Via(expr)->a, Codes);
  1571.             }
  1572.         }
  1573.         }
  1574. #else
  1575.         result = GenExpression(Via(expr)->a, Codes);
  1576.         return result;
  1577. #endif
  1578.     } else {
  1579.         Gen68Error("Illegal conversion");
  1580.     }
  1581.     if (!gProject->itsOptions->useMC68881)
  1582.         SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1583.     } else if (isIntegralType(GetTreeTP(expr))) {
  1584.     if (isIntegralType(GetTreeTP(Via(expr)->a))) {
  1585.         /* Most conversions are here. */
  1586.         if (isBitFieldType(GetTreeTP(expr))) {
  1587.         /*
  1588.          * Convert integer to bit field - what is this useful for ?
  1589.          */
  1590.         result = GenExpression(Via(expr)->a, Codes);
  1591.         return result;
  1592.         } else if (isBitFieldType(GetTreeTP(Via(expr)->a))) {
  1593.         /* Convert bit field to integer, this is the typical case. */
  1594.         unsigned long                   bitmask;
  1595.         temploc = GenExpression(Via(expr)->a, Codes);
  1596.         result = TempDataReg(Codes);
  1597.         if (GetLocSZ(temploc) != M68sz_long)
  1598.             GenInst(M68op_MOVEQ, M68sz_none, BuildImmediate(0, M68sz_long), result, Codes);
  1599.         GenInst(M68op_MOVE, GetLocSZ(temploc), temploc, result, Codes);
  1600.         FreeTemp(temploc);
  1601.         /* Construct a mask, and AND immed */
  1602.         bitmask = MakeMask(temploc);
  1603.         GenInst(M68op_AND, GetLocSZ(temploc), BuildImmediate(bitmask, M68sz_long), result, Codes);
  1604.         ShiftRight(result, GetLocFieldBits(temploc).StartBit, Codes);
  1605.         SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1606.         if (isSignedType(GetTreeTP(Via(expr)->a))) {
  1607.             /*
  1608.              * Here, we test the highest bit of the bit field, and if
  1609.              * it is true, then we OR the result with a mask setting
  1610.              * all the most significant bits.
  1611.              */
  1612.             unsigned long                   himask;
  1613.             LabSYMVia_t                     over;
  1614.             over = MakeEccLabel(NextEccLabel++);
  1615.             GenInst(M68op_BTST, M68sz_none,
  1616.                 BuildImmediate(GetLocFieldBits(temploc).EndBit - GetLocFieldBits(temploc).StartBit, M68sz_long), result, Codes);
  1617.             GenInst(M68op_BEQ, M68sz_none, BuildLabelLoc(over), NULL, Codes);
  1618.             himask =
  1619.             MakeTheMask(GetLocFieldBits(temploc).EndBit - GetLocFieldBits(temploc).StartBit
  1620.                     + 1, 32);
  1621.             GenInst(M68op_OR, GetLocSZ(temploc), BuildImmediate(himask, M68sz_long), result, Codes);
  1622.             GenLabel(over, Codes);
  1623.         }
  1624.         return result;
  1625.         }
  1626.         if (isUnsignedType(GetTreeTP(expr))) {
  1627.         if (isUnsignedType(GetTreeTP(Via(expr)->a))) {
  1628.             if (GetTPSize(GetTreeTP(expr)) > GetTPSize(GetTreeTP(Via(expr)->a))) {
  1629.             temploc = GenExpression(Via(expr)->a, Codes);
  1630.             result = TempDataReg(Codes);
  1631.             if (GetLocSZ(temploc) != M68sz_long)
  1632.                 GenInst(M68op_MOVEQ, M68sz_none, BuildImmediate(0, M68sz_long), result, Codes);
  1633.             GenInst(M68op_MOVE, GetLocSZ(temploc), temploc, result,
  1634.                 Codes);
  1635.             FreeTemp(temploc);
  1636.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1637.             } else if (GetTPSize(GetTreeTP(expr)) < GetTPSize(GetTreeTP(Via(expr)->a))) {
  1638.             temploc = GenExpression(Via(expr)->a, Codes);
  1639.             result = DictateTempDReg(temploc, Codes);
  1640.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1641.             } else {
  1642.             result = GenExpression(Via(expr)->a, Codes);
  1643.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1644.             }
  1645.         } else {
  1646.             if (GetTPSize(GetTreeTP(expr)) > GetTPSize(GetTreeTP(Via(expr)->a))) {
  1647.             temploc = GenExpression(Via(expr)->a, Codes);
  1648.             result = TempDataReg(Codes);
  1649.             if (GetLocSZ(temploc) != M68sz_long)
  1650.                 GenInst(M68op_MOVEQ, M68sz_none, BuildImmediate(0, M68sz_long), result, Codes);
  1651.             GenInst(M68op_MOVE, GetLocSZ(temploc), temploc, result,
  1652.                 Codes);
  1653.             FreeTemp(temploc);
  1654.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1655.             } else if (GetTPSize(GetTreeTP(expr)) < GetTPSize(GetTreeTP(Via(expr)->a))) {
  1656.             temploc = GenExpression(Via(expr)->a, Codes);
  1657.             result = DictateTempDReg(temploc, Codes);
  1658.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1659.             } else {
  1660.             result = GenExpression(Via(expr)->a, Codes);
  1661.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1662.             }
  1663.         }
  1664.         } else {
  1665.         if (isUnsignedType(GetTreeTP(Via(expr)->a))) {
  1666.             if (GetTPSize(GetTreeTP(expr)) > GetTPSize(GetTreeTP(Via(expr)->a))) {
  1667.             temploc = GenExpression(Via(expr)->a, Codes);
  1668.             result = TempDataReg(Codes);
  1669.             if (GetLocSZ(temploc) != M68sz_long)
  1670.                 GenInst(M68op_MOVEQ, M68sz_none, BuildImmediate(0, M68sz_long), result, Codes);
  1671.             GenInst(M68op_MOVE, GetLocSZ(temploc), temploc, result,
  1672.                 Codes);
  1673.             FreeTemp(temploc);
  1674.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1675.             } else if (GetTPSize(GetTreeTP(expr)) < GetTPSize(GetTreeTP(Via(expr)->a))) {
  1676.             temploc = GenExpression(Via(expr)->a, Codes);
  1677.             result = DictateTempDReg(temploc, Codes);
  1678.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1679.             } else {
  1680.             result = GenExpression(Via(expr)->a, Codes);
  1681.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1682.             }
  1683.         } else {
  1684.             if (GetTPSize(GetTreeTP(expr)) > GetTPSize(GetTreeTP(Via(expr)->a))) {
  1685.             temploc = GenExpression(Via(expr)->a, Codes);
  1686.             result = TempDataReg(Codes);
  1687.             GenInst(M68op_MOVE, GetLocSZ(temploc), temploc, result, Codes);
  1688.             FreeTemp(temploc);
  1689.             if (GetTPSize(GetTreeTP(Via(expr)->a)) == 1) {
  1690.                 GenInst(M68op_EXT, M68sz_word, result, NULL, Codes);
  1691.             }
  1692.             if (GetTPSize(GetTreeTP(expr)) == 4) {
  1693.                 GenInst(M68op_EXT, M68sz_long, result, NULL, Codes);
  1694.             }
  1695.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1696.             } else if (GetTPSize(GetTreeTP(expr)) < GetTPSize(GetTreeTP(Via(expr)->a))) {
  1697.             temploc = GenExpression(Via(expr)->a, Codes);
  1698.             if (isConstantLoc(temploc)) {
  1699.                 result = temploc;
  1700.             }
  1701.             else {
  1702.                 result = DictateTempDReg(temploc, Codes);
  1703.             }
  1704.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1705.             } else {
  1706.             result = GenExpression(Via(expr)->a, Codes);
  1707.             SetLocSZ(result, GetTPSize(GetTreeTP(expr)));
  1708.             }
  1709.         }
  1710.         }
  1711.     } else if (isFloatingType(GetTreeTP(Via(expr)->a))) {
  1712.         if (gProject->itsOptions->useMC68881) {
  1713.         /* We will assume that the destination type is long. */
  1714.         temploc = GenExpression(Via(expr)->a, Codes);
  1715.         result = TempFloatReg(Codes);
  1716.         GenInst(M68op_FINTRZ, GetLocSZ(temploc), temploc, result, Codes);
  1717.         SetLocSZ(result, M68sz_long);
  1718.         FreeTemp(temploc);
  1719.         } else {
  1720.         /* We will assume that the destination type is long. */
  1721.         SpillSlotVia_t                  slot;
  1722.         temploc = GenExpression(Via(expr)->a, Codes);
  1723.         temploc = DictateTempFloat(temploc, Codes);
  1724.         slot = GetSpillSlot(M68sz_long);
  1725.         result = Via(slot)->SlotLoc;
  1726.         GenSANECall(FFEXT + FOTTI, temploc, NULL, Codes);
  1727.         GenPushEA(temploc, Codes);
  1728.         SaveDataRegisters(Codes);
  1729.             GenInst(M68op_JSR, M68sz_none,
  1730.                 BuildARegLabelDisplace(5, LibLabelXTOI), NULL, Codes);
  1731.         GenInst(M68op_MOVE, M68sz_long, BuildDRegLocation(0), result, Codes);
  1732.         SetLocSZ(result, M68sz_long);
  1733.         FreeTemp(temploc);
  1734.         }
  1735.     } else if (isPointerType(GetTreeTP(Via(expr)->a))) {
  1736.         temploc = GenExpression(Via(expr)->a, Codes);
  1737.         result = TempDataReg(Codes);
  1738.         GenInst(M68op_MOVE, M68sz_long, temploc, result, Codes);
  1739.         SetLocSZ(result, M68sz_long);
  1740.         FreeTemp(temploc);
  1741.     } else {
  1742.         Gen68Error("Illegal conversion");
  1743.     }
  1744.     } else if (isPointerType(GetTreeTP(expr))) {
  1745.     if (isPointerType(GetTreeTP(Via(expr)->a))) {
  1746.         result = GenExpression(Via(expr)->a, Codes);
  1747.     } else if (isIntegralType(GetTreeTP(Via(expr)->a))) {
  1748.         result = GenExpression(Via(expr)->a, Codes);
  1749.         result = DictateTempAReg(result, Codes);
  1750.         SetLocSZ(result, M68sz_long);
  1751.  
  1752.     } else if (isArrayType(GetTreeTP(Via(expr)->a)) ||
  1753.            isStructUnionType(GetTreeTP(Via(expr)->a))) {
  1754.         result = GenAddrOf(Via(expr)->a, Codes);
  1755.     } else {
  1756.         Gen68Error("Illegal conversion");
  1757.     }
  1758.     } else if (isStructUnionType(GetTreeTP(expr))) {
  1759.     if (isStructUnionType(GetTreeTP(Via(expr)->a))) {
  1760.         result = GenExpression(Via(expr)->a, Codes);
  1761.     } else {
  1762.         Gen68Error("Illegal conversion");
  1763.     }
  1764.     } else if (isVoidType(GetTreeTP(expr))) {
  1765.     result = GenExpression(Via(expr)->a, Codes);
  1766.     result = NULL;
  1767.     } else {
  1768.     result = GenExpression(Via(expr)->a, Codes);
  1769.     SetLocSZ(result, M68_TypeSize(GetTreeTP(expr)));
  1770.     }
  1771.     return result;
  1772. }
  1773.